#include <iostream>
#include <cstdlib>
#include <memory>  // 包含 unique_ptr 所在的头文件
/*
    垃圾回收（Garbage Collection，GC）机制是一种自动管理内存分配和回收的技术，用于防止程序中出现内存泄漏和其他与内存管理相关的问题。垃圾回收的基本原理是通过自动检测不再使用的对象，并将其占用的内存空间释放，使这些内存可供程序再次使用。
    在C++中，垃圾回收机制是通过智能指针（Smart Pointer）实现的。智能指针是一种特殊的指针，它能够自动检测不再使用的对象，并将其占用的内存空间释放。因此，程序员在使用智能指针时，不需要手动释放内存空间，从而简化了内存管理的操作。
*/

class Person;// 前置 声明
class Car
{
public:
    Car()
    {
        std::cout << "Car()" << std::endl;
    }

    ~Car()
    {
        std::cout << "~Car()" << std::endl;
    }

public:
    // weak_ptr 解决 shared_ptr 循环引用问题
    std::weak_ptr<Person> m_person;

};

class Person
{
public:
    Person()
    {
        std::cout << "Person()" << std::endl;
    }

    Person(int age):m_age(age)
    {
        std::cout << "Person(int age)" << std::endl;
    }

    ~Person()
    {
        std::cout << "~Person()" << std::endl;
    }

public:// 成员函数尽量 单独在另一个 public中
    /* 成员函数 */
    void run()
    {
        std::cout << "run()--age : " << m_age << std::endl;
    }
public:
    std::shared_ptr<Car> m_car = nullptr;


private:
    int m_age;
    
};

int main(int argc, char *argv[])
{
#if 0
    // 多个 shared_ptr 可以指向 同一个对象，当最后一个 shared_ptr 在作用域范围内结束时，对象才会被自动释放
    {
        std::shared_ptr<Person> p2;
        std::cout << "111" << std::endl;
        {
            std::shared_ptr<Person> p1(new Person(30));
            p1->run();
            std::cout << "cnt:" << p1.use_count() << std::endl; // 1
            
            p2 = p1;
            std::cout << "cnt:" << p2.use_count() << std::endl; // 2
        }
        std::cout << "cnt:" << p2.use_count() << std::endl;     // 1
        std::cout << "222" << std::endl;
    }       
    std::cout << "333" << std::endl;


    // shared_ptr 解决了 auto_ptr 遗留的数组问题
    std::shared_ptr<Person[]> person(new Person[5]{});
    /* 数组使用 */
    person[2].run();
#if 0
    // 等价于 Person * arr = new Person[5]{};
    //       delete [] arr;
#endif

    person.use_count();

#endif

    std::shared_ptr<Person> person(new Person);
    std::shared_ptr<Car> car(new Car);

    person->m_car = car;
    car->m_person = person;

    return 0;
}